package cz.fimuni.pa165.frontend.restservice;

import com.google.gson.Gson;
import cz.fimuni.pa165.backendapi.dto.CarDTO;
import cz.fimuni.pa165.backendapi.dto.CompanyDTO;
import cz.fimuni.pa165.backendapi.dto.EmployeeDTO;
import cz.fimuni.pa165.backendapi.dto.ReservationDTO;
import cz.fimuni.pa165.backendapi.facade.ServiceFacade;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 *
 * @author Ondra + Lukáš Slovák
 */
@Controller
@RequestMapping("/rest/company")
public class CompanyRestService implements CompanyRestServiceInterface{
    
    @Autowired
    private ServiceFacade serviceFacade;
    @Autowired
    private Gson gson;
    
    @RequestMapping(value = "/add", method = RequestMethod.POST, headers = "Content-Type=application/json")
    @ResponseBody
    @Override
    public ResponseEntity<String> addCompany(@RequestBody String json) {
        Authentication auth = new UsernamePasswordAuthenticationToken("pa165", "pa165") ;
        SecurityContextHolder.getContext().setAuthentication(auth);
        CompanyDTO compDTO = gson.fromJson(json, CompanyDTO.class);
        
        if ( companyExists(compDTO.getName())) {
            SecurityContextHolder.getContext().setAuthentication(null);
            return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
        }else{
            serviceFacade.addCompany(compDTO);
            SecurityContextHolder.getContext().setAuthentication(null);
            return new ResponseEntity<String>(HttpStatus.ACCEPTED);
        }
    }
    
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    @Override
    public ResponseEntity<String> deleteCompany(@PathVariable Long id) {
        try {
            Authentication auth = new UsernamePasswordAuthenticationToken("rest", "rest") ;
            SecurityContextHolder.getContext().setAuthentication(auth);
            serviceFacade.removeCompany(serviceFacade.getCompanyById(id));
            SecurityContextHolder.getContext().setAuthentication(null);
            return new ResponseEntity<String>(HttpStatus.OK);
        } catch (JpaSystemException e) {
            List<CarDTO> dtoList = serviceFacade.getAllCars();         
            for (int i = 0; i < dtoList.size(); i++) {
                if (dtoList.get(i).getCompany().getId().equals(id)) {
                    try {
                        deleteCar(dtoList.get(i));
                    } catch (JpaSystemException ex) {
                        SecurityContextHolder.getContext().setAuthentication(null);
                        return new ResponseEntity<String>(HttpStatus.FORBIDDEN);
                    }
                }
            }
            List<EmployeeDTO> listEmp = serviceFacade.findEmployeesByCompany(
                                                        serviceFacade.getCompanyById(id));
            for (int i = 0; i < listEmp.size(); i++){
                EmployeeDTO emp = listEmp.get(i);
                try {
                    deleteEmployee(emp); 
                } catch (JpaSystemException ex) {
                    SecurityContextHolder.getContext().setAuthentication(null);
                    return new ResponseEntity<String>(HttpStatus.FORBIDDEN);
                }
            }
            try{
                serviceFacade.removeCompany(serviceFacade.getCompanyById(id));
                SecurityContextHolder.getContext().setAuthentication(null);
                return new ResponseEntity<String>(HttpStatus.OK);
            }catch (JpaSystemException ex){
                SecurityContextHolder.getContext().setAuthentication(null);
                return new ResponseEntity<String>(HttpStatus.FORBIDDEN);
            }   
        }
    }
    
    @RequestMapping(value = "/all", method = RequestMethod.GET)
    @ResponseBody
    @Override
    public ResponseEntity<String> companyHome() {
        Authentication auth = new UsernamePasswordAuthenticationToken("rest", "rest") ;
        SecurityContextHolder.getContext().setAuthentication(auth);
        String response = gson.toJson(serviceFacade.getAllCompanies());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json; charset=utf-8");
        SecurityContextHolder.getContext().setAuthentication(null);
        return new ResponseEntity<String>(response, headers, HttpStatus.OK);
    }
    
    @RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
    @ResponseBody
    @Override
    public ResponseEntity<String> companyGet(@PathVariable(value = "id") Long id) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json; charset=utf-8");
        Authentication auth = new UsernamePasswordAuthenticationToken("rest", "rest") ;
        SecurityContextHolder.getContext().setAuthentication(auth);
        String car = gson.toJson(serviceFacade.getCompanyById(id));
        SecurityContextHolder.getContext().setAuthentication(null);
        return new ResponseEntity<String>(car, headers, HttpStatus.OK);
    }

    @RequestMapping(value = "/edit", method = RequestMethod.POST, headers = "Content-Type=application/json")
    @ResponseBody
    @Override
    public ResponseEntity<String> companyEdit(@RequestBody String json) {
        CompanyDTO compDTO = gson.fromJson(json, CompanyDTO.class);
        String input1 = compDTO.getName().trim();
        String input2 = compDTO.getAdress().trim();
        Authentication auth = new UsernamePasswordAuthenticationToken("rest", "rest") ;
        SecurityContextHolder.getContext().setAuthentication(auth);
        if ( otherCompanyExists(input1,compDTO.getId())){
            SecurityContextHolder.getContext().setAuthentication(null);
            return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
        }else{
            serviceFacade.updateCompany(compDTO);
            SecurityContextHolder.getContext().setAuthentication(null);
            return new ResponseEntity<String>(HttpStatus.ACCEPTED);
        }
    }

    private boolean companyExists(String name) {
         List<CompanyDTO> list = serviceFacade.getAllCompanies();
         for(CompanyDTO comp : list){
             if( (comp.getName().equals(name)) ){ return true;}
         }
         return false;
    }
    
    private boolean otherCompanyExists(String name, Long id) {
        List<CompanyDTO> list = serviceFacade.getAllCompanies();
         for(CompanyDTO comp : list){
             if( (comp.getName().equals(name)) &&
                 (!comp.getId().equals(id))   ){
                    return true;
             }
         }
         return false;
    }
    
     private void deleteCar(CarDTO car) throws JpaSystemException{
        List<ReservationDTO> dtoList = serviceFacade.getAllReservations();
        for (int i = 0; i < dtoList.size(); i++) {
            if (dtoList.get(i).getCar().getId().equals(car.getId())) {
                    serviceFacade.removeReservation(dtoList.get(i));                    
            }
        }
        serviceFacade.removeCar(car);  
   }
     
     private void deleteEmployee(EmployeeDTO emp) throws JpaSystemException{
        List<ReservationDTO> listRes = serviceFacade.getReservationByEmployee(emp);
        for (int j = 0; j < listRes.size(); j++){
            serviceFacade.removeReservation(listRes.get(j));
        }
        serviceFacade.removeEmployee(emp);
    }
}
